<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>访问日志地图可视化</title>
	<link rel="stylesheet" href="../../component/pear/css/pear.css" />
	<style>
		/* 地图容器样式：适配 Pear Admin 卡片布局 */
		#map-container {
			width: 100%;
			height: 600px;
			border-radius: 4px;
			box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
			margin-top: 10px;
		}
		/* 统计卡片样式：与查询表单对齐 */
		.stat-card-group {
			display: flex;
			flex-wrap: wrap;
			gap: 16px;
			margin-bottom: 16px;
		}
		.stat-card {
			flex: 1;
			min-width: 200px;
			padding: 16px;
			background: #fff;
			border-radius: 4px;
			box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
		}
		.stat-card-title {
			font-size: 14px;
			color: #666;
			margin-bottom: 8px;
		}
		.stat-card-value {
			font-size: 24px;
			font-weight: 600;
			color: #1E9FFF;
		}
	</style>
</head>

<body class="pear-container">
	<!-- 1. 查询表单卡片（与账户管理页面样式一致） -->
	<div class="layui-card">
		<div class="layui-card-body">
			<form class="layui-form" action="">
				<div class="layui-form-item">
					<!-- 访问IP查询 -->
					<div class="layui-form-item layui-inline">
						<label class="layui-form-label">访问IP</label>
						<div class="layui-input-inline">
							<input type="text" name="ip" id="ip" placeholder="输入IP查询" class="layui-input">
						</div>
					</div>
					<!-- 访问区域查询 -->
					<div class="layui-form-item layui-inline">
						<label class="layui-form-label">访问区域</label>
						<div class="layui-input-inline">
							<input type="text" name="region" id="region" placeholder="如：江苏省" class="layui-input">
						</div>
					</div>
					<!-- 访问城市查询 -->
					<div class="layui-form-item layui-inline">
						<label class="layui-form-label">访问城市</label>
						<div class="layui-input-inline">
							<input type="text" name="city" id="city" placeholder="如：南京市" class="layui-input">
						</div>
					</div>
					<!-- 时间范围查询 -->
					<div class="layui-form-item layui-inline">
						<label class="layui-form-label">访问时间</label>
						<div class="layui-input-inline">
							<input type="text" name="time_range" id="time_range" placeholder="选择时间范围" class="layui-input">
						</div>
					</div>
					<br>
					<!-- 查询/重置按钮 -->
					<div class="layui-form-item layui-inline">
						<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="map-query">
							<i class="layui-icon layui-icon-search"></i>
							查询
						</button>
						<button type="reset" class="pear-btn pear-btn-md">
							<i class="layui-icon layui-icon-refresh"></i>
							重置
						</button>
					</div>
				</div>
			</form>
		</div>
	</div>

	<!-- 2. 统计卡片 + 地图卡片（合并在一个卡片内，保持布局统一） -->
	<div class="layui-card">
		<div class="layui-card-body">
			<!-- 统计概览卡片组 -->
			<div class="stat-card-group">
				<div class="stat-card">
					<div class="stat-card-title">总访问次数</div>
					<div class="stat-card-value" id="total-access">0</div>
				</div>
				<div class="stat-card">
					<div class="stat-card-title">独立IP数</div>
					<div class="stat-card-value" id="ip-count">0</div>
				</div>
				<div class="stat-card">
					<div class="stat-card-title">访问省份数</div>
					<div class="stat-card-value" id="region-count">0</div>
				</div>
				<div class="stat-card">
					<div class="stat-card-title">访问城市数</div>
					<div class="stat-card-value" id="city-count">0</div>
				</div>
			</div>

			<!-- 地图容器 -->
			<div id="map-container"></div>
		</div>
	</div>

	<!-- 3. 访问日志表格卡片（与账户管理页面表格样式一致） -->
	<div class="layui-card">
		<div class="layui-card-body">
			<table id="map-log-table" lay-filter="map-log-table"></table>
		</div>
	</div>

	<!-- 4. 表格工具栏模板（复用账户管理页面风格） -->
	<script type="text/html" id="map-log-toolbar">
		<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="export">
			<i class="layui-icon layui-icon-export"></i>
			导出日志
		</button>
		<button class="pear-btn pear-btn-md" lay-event="refresh">
			<i class="layui-icon layui-icon-refresh"></i>
			刷新
		</button>
	</script>

	<!-- 5. 表格列模板（时间格式化、IP显示等） -->
	<script type="text/html" id="map-log-accessTime">
		{{layui.util.toDateString(d.access_time, 'yyyy-MM-dd HH:mm:ss')}}
	</script>
	<script type="text/html" id="map-log-ip">
		<span style="color: #1E9FFF;">{{d.ip}}</span>
	</script>
	<script type="text/html" id="map-log-region">
		{{d.region || '未知省份'}}
	</script>
	<script type="text/html" id="map-log-city">
		{{d.city || '未知城市'}}
	</script>
	<script type="text/html" id="map-log-userAgent">
		{{d.user_agent || '未知设备'}}
	</script>

	<!-- 6. 引入 Pear Admin 核心资源（与账户管理页面一致） -->
	<script src="../../component/com/api.js"></script>
	<script src="../../component/com/auth.js"></script>
	<script src="../../component/layui/layui.js"></script>
	<script src="../../component/pear/pear.js"></script>
	<script>
		layui.use(['table', 'form', 'jquery', 'common', 'laydate', 'echarts'], function () {
			let table = layui.table;
			let form = layui.form;
			let $ = layui.jquery;
			let common = layui.common;
			let laydate = layui.laydate;
			let echarts = layui.echarts;
			let MODULE_PATH = "system/"; // 页面所在模块路径（根据实际调整）
			let API_BASE_URL = apiConfig.baseUrl;
			let token = window.localStorage.getItem("token") || window.sessionStorage.getItem("token");
			let mapChart = null; // 地图实例（全局保存，便于刷新）

			// -------------------------- 1. 初始化时间范围选择器 --------------------------
			laydate.render({
				elem: '#time_range',
				type: 'datetime',
				range: true, // 开启时间范围选择
				format: 'yyyy-MM-dd HH:mm:ss',
				placeholder: '开始时间 - 结束时间'
			});

			// -------------------------- 2. 初始化地图 --------------------------
			function initMap(mapData) {
				// 销毁已有地图实例（避免重复渲染）
				if (mapChart) {
					mapChart.dispose();
				}
				// 创建新地图实例
				mapChart = echarts.init(document.getElementById('map-container'));

				// 加载中国地图JSON（Pear Admin 内置路径，若不存在需手动下载放入对应目录）
				$.get('../../component/echarts/map/json/china.json', function (chinaJson) {
					echarts.registerMap('china', chinaJson);

					// 地图配置项（贴合 Pear Admin 蓝色系风格）
					let option = {
						title: {
							text: '系统全国访问分布',
							left: 'center',
							textStyle: {
								fontSize: 16,
								color: '#333'
							}
						},
						tooltip: {
							trigger: 'item',
							padding: 10,
							backgroundColor: 'rgba(255,255,255,0.9)',
							borderColor: '#1E9FFF',
							borderWidth: 1,
							formatter: function (params) {
								return `
									<div style="text-align: left;">
										<p>IP：${params.data[4]}</p>
										<p>区域：${params.data[3]}（${params.data[2]}次访问）</p>
										<p>最近访问：${params.data[5]}</p>
									</div>
								`;
							}
						},
						visualMap: {
							min: 1,
							max: 20, // 最大访问次数（根据实际数据调整）
							left: 'left',
							top: 'bottom',
							text: ['访问频繁', '访问较少'],
							textStyle: {
								fontSize: 12,
								color: '#666'
							},
							calculable: true,
							inRange: {
								color: ['#e0f7fa', '#4dd0e1', '#0097a7'] // 贴合 Pear Admin 蓝色系
							}
						},
						geo: {
							map: 'china',
							roam: true, // 允许缩放、拖拽
							label: {
								normal: {
									show: true,
									fontSize: 10,
									color: '#666'
								},
								emphasis: {
									show: true,
									color: '#1E9FFF',
									fontWeight: 'bold'
								}
							},
							itemStyle: {
								normal: {
									areaColor: '#f5fafe',
									borderColor: '#e0e0e0'
								},
								emphasis: {
									areaColor: '#e0f7fa',
									borderColor: '#1E9FFF'
								}
							}
						},
						series: [{
							name: '访问记录',
							type: 'scatter',
							coordinateSystem: 'geo',
							data: mapData,
							symbolSize: function (val) {
								// 气泡大小：访问次数越多，气泡越大（10~30px）
								return 10 + val[2] * 1;
							},
							symbol: 'circle',
							itemStyle: {
								color: '#1E9FFF',
								shadowBlur: 8,
								shadowColor: 'rgba(30, 159, 255, 0.3)'
							}
						}]
					};

					// 渲染地图
					mapChart.setOption(option);
					// 窗口大小自适应
					window.addEventListener('resize', function () {
						mapChart.resize();
					});
				});
			}

			// -------------------------- 3. 加载地图 + 表格数据 --------------------------
			function loadData(params = {}) {
				// 添加请求头（携带token）
				$.ajaxSetup({
					headers: {
						"Authorization": token
					}
				});

				// 1. 请求地图数据
				$.get(`${API_BASE_URL}/api/access-map-data/`, params, function (res) {
					if (res.success) {
						let mapData = res.data.map_data;
						let regionStats = res.data.region_stats;
						let logList = res.data.log_list;

						// 更新统计卡片数据
						updateStatCard(mapData, regionStats, logList);
						// 初始化/刷新地图
						initMap(mapData);
						// 渲染表格数据
						renderTable(logList, params);
					} else {
						layer.msg(res.message, { icon: 2 });
					}
				}).fail(function () {
					layer.msg('数据加载失败，请重试', { icon: 2 });
				});
			}

			// -------------------------- 4. 更新统计卡片数据 --------------------------
			function updateStatCard(mapData, regionStats, logList) {
				// 总访问次数（所有IP访问次数之和）
				let totalAccess = mapData.reduce((sum, item) => sum + item[2], 0);
				// 独立IP数（去重）
				let ipSet = new Set(mapData.map(item => item[4]));
				// 访问省份数
				let regionCount = regionStats.length;
				// 访问城市数（去重）
				let citySet = new Set(mapData.map(item => item[3]));

				// 更新DOM
				$('#total-access').text(totalAccess);
				$('#ip-count').text(ipSet.size);
				$('#region-count').text(regionCount);
				$('#city-count').text(citySet.size);
			}

			// -------------------------- 5. 渲染访问日志表格 --------------------------
			function renderTable(logList, queryParams) {
				table.render({
					elem: '#map-log-table',
					data: logList, // 本地数据（也可改为url远程请求，与账户管理页面一致）
					page: true,
					request: {
						pageName: 'page',
						limitName: 'limit'
					},
					limits: [10, 20, 30, 50],
					limit: 10,
					cols: [[
						{ type: 'checkbox', fixed: 'left' },
						{ title: '序号', field: 'id', align: 'left', width: 80, fixed: 'left' },
						{ title: '访问IP', field: 'ip', align: 'center', width: 150, templet: '#map-log-ip' },
						{ title: '访问省份', field: 'region', align: 'center', width: 120, templet: '#map-log-region' },
						{ title: '访问城市', field: 'city', align: 'center', width: 120, templet: '#map-log-city' },
						{ title: '访问时间', field: 'access_time', align: 'center', width: 180, templet: '#map-log-accessTime' },
						{ title: '设备信息', field: 'user_agent', align: 'left', minWidth: 200, templet: '#map-log-userAgent' },
						{ title: '操作', align: 'center', width: 120, toolbar: `#map-log-bar` }
					]],
					skin: 'line',
					toolbar: '#map-log-toolbar',
					defaultToolbar: ['filter', 'print', 'exports'],
					parseData: function (res) {
						return {
							"code": res.success ? 0 : 1,
							"msg": res.message || "操作成功",
							"count": res.data.count || logList.length,
							"data": res.data.results || logList
						};
					}
				});
			}

			// -------------------------- 6. 表格工具栏事件 --------------------------
			table.on('toolbar(map-log-table)', function (obj) {
				switch (obj.event) {
					case "export":
						layer.msg('导出功能开发中', { icon: 1 });
						break;
					case "refresh":
						// 重置表单并刷新数据
						$('form')[0].reset();
						loadData();
						break;
				}
			});

			// -------------------------- 7. 查询表单提交
            // -------------------------- 7. 表格行操作事件 --------------------------
			table.on('tool(map-log-table)', function (obj) {
				let data = obj.data; // 当前行数据
				switch (obj.event) {
					case "detail":
						// 查看访问详情
						showDetail(data);
						break;
					case "delete":
						// 删除单条访问记录
						deleteLog(obj, data.id);
						break;
				}
			});

			// -------------------------- 8. 查询表单提交事件 --------------------------
			form.on('submit(map-query)', function (data) {
				// 格式化查询参数（处理时间范围）
				let queryParams = { ...data.field };
				if (queryParams.time_range) {
					// 拆分时间范围为开始时间和结束时间（后端可能需要单独参数）
					let [startTime, endTime] = queryParams.time_range.split(' - ');
					queryParams.start_time = startTime;
					queryParams.end_time = endTime;
					delete queryParams.time_range; // 删除原始合并字段
				}
				// 加载筛选后的数据
				loadData(queryParams);
				return false; // 阻止表单默认提交
			});

			// -------------------------- 9. 辅助函数：导出日志 --------------------------
			function exportLogs() {
				if (!token) {
					layer.msg('请先登录', { icon: 2 });
					return;
				}
				// 构建导出URL（携带当前查询参数）
				let exportUrl = `${API_BASE_URL}/common/access/log/export/?`;
				Object.keys(currentParams).forEach(key => {
					exportUrl += `${key}=${encodeURIComponent(currentParams[key])}&`;
				});
				exportUrl += `token=${token}`;

				// 创建隐藏iframe实现下载
				let iframe = document.createElement('iframe');
				iframe.style.display = 'none';
				iframe.src = exportUrl;
				document.body.appendChild(iframe);
				// 下载完成后移除iframe
				setTimeout(() => {
					document.body.removeChild(iframe);
				}, 3000);
			}

			// -------------------------- 10. 辅助函数：显示访问详情 --------------------------
			function showDetail(data) {
				// 格式化详情内容
				let detailHtml = `
					<table class="layui-table" style="margin: 0;">
						<tr><td width="30%">访问IP</td><td>${data.ip || '未知'}</td></tr>
						<tr><td>访问区域</td><td>${data.region || '未知省份'}</td></tr>
						<tr><td>访问城市</td><td>${data.city || '未知城市'}</td></tr>
						<tr><td>经纬度</td><td>${data.longitude || ''}, ${data.latitude || ''}</td></tr>
						<tr><td>访问时间</td><td>${layui.util.toDateString(data.access_time, 'yyyy-MM-dd HH:mm:ss')}</td></tr>
						<tr><td>设备信息</td><td>${data.user_agent || '未知设备'}</td></tr>
					</table>
				`;
				// 打开详情弹窗
				layer.open({
					type: 1,
					title: '访问详情',
					area: ['500px', 'auto'],
					content: detailHtml,
					btn: ['关闭'],
					btnAlign: 'c'
				});
			}

			// -------------------------- 11. 辅助函数：删除访问记录 --------------------------
			function deleteLog(obj, logId) {
				layer.confirm('确定要删除这条访问记录吗？', {
					icon: 3,
					title: '提示'
				}, function (index) {
					layer.close(index);
					let loading = layer.load();
					// 发送删除请求
					$.ajax({
						url: `${API_BASE_URL}/api/access-log/${logId}/`,
						type: 'DELETE',
						headers: {
							"Authorization": token
						},
						success: function (res) {
							layer.close(loading);
							if (res.success) {
								layer.msg('删除成功', { icon: 1, time: 1000 }, function () {
									// 删除表格行并刷新数据
									obj.del();
									loadData(currentParams);
								});
							} else {
								layer.msg(res.message || '删除失败', { icon: 2 });
							}
						},
						error: function () {
							layer.close(loading);
							layer.msg('服务器异常，删除失败', { icon: 2 });
						}
					});
				});
			}

			// -------------------------- 12. 页面初始化：加载默认数据 --------------------------
			$(function () {
				// 页面加载完成后自动加载数据
				loadData();
			});
		});
	</script>
</body>

</html>